package com.itHaipeng.utils;

import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 用于记录日志的工具类，它里面提供了公共的代码
 */
public class Logger {
    /**
     * 用于打印日志，计划让其在切入点方法在执行之前执行（切入点方法就是业务层方法）
     */
    public void printLogger(){
        System.out.println("");
    }

    /**
     * 前置通知
     *
     */
    public void beforePrintLogger(){
        System.out.println("前置通知:logger类中的beforePrintLogger方法开始记录日志了。。。。");
    }
    /**
     * 后置通知
     */
    public void afterReturningPrintLogger(){
        System.out.println("后置通知:logger类中的afterReturningPrintLogger方法开始记录日志了。。。。");
    }
    /**
     *异常通知
     */
    public void afterThrowingPrintLogger(){
        System.out.println("异常通知:logger类中的afterThrowingPrintLogger方法开始记录日志了。。。。");
    }
    /**
     * 最终通知
     */
    public void afterPrintLogger(){
        System.out.println("最终通知:logger类中的afterPrintLogger方法开始记录日志了。。。。");
    }
    /**
     * 环绕通知
     * 问题：当我们配置了环绕通知后，切入点方法没有执行，而通知方法执行了
     * 分析原因：
     *    在我们配置invoke时，整个方法也叫环绕通知，通过对比动态代理中的环绕通知代码
     *      发现动态代理中的环绕通知有明确的切入点方法调用，而我们代码中没有
     * 解决问题：
     *    spring框架为我们提供了一个接口：ProceedingJoinPoint
     *      该接口有一个方法叫做proceed()这个方法相当于明确调用切入点方法。
     *      该接口可以作为环绕通知的方法参数，在程序执行时，spring框架会为我们提供该接口的实现类，来供我们使用
     * spring环绕通知它时spring框架为我们提供的一种方式，一种可以在代码中手动控制增强方法何时执行的方式
     */
    public Object aroundPrintLogger(ProceedingJoinPoint proceedingJoinPoint){
        try {
                Object[] args=proceedingJoinPoint.getArgs();//得到方法执行所需的参数
            System.out.println("环绕通知:logger类中的aroundPrintLogger方法开始记录日志了。。。。");//表示前置通知通知
            Object value = proceedingJoinPoint.proceed(args);//明确调用业务层方法，也叫切入点方法
             /**
             * Throwable Exception拦不住它
             */
             return value;
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}
